package com.ego.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ego.auth.entity.UserInfo;
import com.ego.exception.EgoException;
import com.ego.exception.ExceptionEnum;
import com.ego.order.client.GoodsClient;
import com.ego.order.config.PayHelper;
import com.ego.order.interceptor.LoginInterceptor;
import com.ego.order.mapper.*;
import com.ego.order.pojo.*;
import com.ego.order.service.OrderService;
import com.ego.order.service.PayLogService;
import com.ego.pojo.Sku;
import com.ego.pojo.utils.IdWorker;
import com.ego.pojo.vo.ResultVO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author Ares
 * @date 2020-12-11
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private OrderStatusMapper orderStatusMapper;
    @Resource
    private PayLogService payLogService;
    @Resource
    private PayLogMapper payLogMapper;
    @Resource
    private IdWorker idWorker;
    @Resource
    private GoodsClient goodsClient;
    @Resource
    private AmqpTemplate amqpTemplate;
    @Resource
    private PayHelper payHelper;
    @Resource
    private SeckillOrderMapper seckillOrderMapper;

    @Override
    @GlobalTransactional(name = "submitOrder")
    public void createOrder(Order order) {
        try{
            //获取当前登录用户
            UserInfo userInfo = LoginInterceptor.getCurrUser();
            //根据IDWorker生成一个唯一的ID
            long orderId = idWorker.nextId();
            //注入order中的一些参数
            order.setOrderId(orderId);
            order.setCreateTime(new Date());
            order.setUserId(userInfo.getId());
            order.setBuyerNick(userInfo.getUsername());
            //将order添加到数据库中
            orderMapper.insert(order);
            //获取到orderDetail集合
            List<OrderDetail> details = order.getOrderDetails();
            //获取skuId集合
            List<Long> skuIdList = details.stream().map(detail -> detail.getSkuId()).collect(Collectors.toList());
            //通过Feign调用方法使用skuId集合查询sku集合
            List<Sku> skus = goodsClient.querySkuListByIds(skuIdList).getBody();
            //使用原子性定义一个总价格
            AtomicReference<Long> totalPay = new AtomicReference<>(0L);
            Map<Long, Integer> stockData = new HashMap<>();
            //获取每一个商品的具体信息
            details.forEach(orderDetail -> {
                Sku dbSku = skus.stream().filter(sku -> sku.getId().equals(orderDetail.getSkuId())).findAny().get();
                orderDetail.setOrderId(orderId);
                orderDetail.setPrice(dbSku.getPrice());
                orderDetail.setTitle(dbSku.getTitle());
                totalPay.updateAndGet(v -> v + orderDetail.getPrice() * orderDetail.getCount());
                //将orderDetail的信息添加到数据库
                orderDetailMapper.insert(orderDetail);
                stockData.put(orderDetail.getSkuId(), orderDetail.getCount());
            });
            //判断前端传过来的总价和后端查询后计算的总价是否一样
            if(!totalPay.get().equals(order.getTotalPay())){
                EgoException.error(log, ExceptionEnum.ORDER_PARAMS_EXCEPTION);
            }
            //构建orderStatus实体
            OrderStatus orderStatus = OrderStatus.builder().orderId(orderId).createTime(order.getCreateTime()).status(1).build();
            //将orderStatus添加到数据库中
            orderStatusMapper.insert(orderStatus);
            //发送消息到消息队列中
            goodsClient.descrementStock(stockData);
            try{
                Map<String, Object> data = new HashMap<>(2);
                data.put("userId",userInfo.getId());
                data.put("skuIdList",skuIdList);
                amqpTemplate.convertAndSend("ego.order.exchange","order.submit",data);
            }catch (Exception e){
                log.error("发送消息到交换机异常",e);
            }
        }catch (Exception e){
            EgoException.error(log,ExceptionEnum.ORDER_SUBMIT_EXCEPTION,e);
        }
    }

    @Override
    public String generateUrl(Long orderId) {
        //根据订单ID查询订单
        OrderStatus orderStatus = orderStatusMapper.selectById(orderId);
        //判断订单状态
        if (!orderStatus.getStatus().equals(com.ego.order.enums.OrderStatusEnum.INIT.value())) {
            throw new EgoException(ExceptionEnum.ORDER_STATUS_EXCEPTION);
        }

        //TODO 这里传入一份钱，用于测试使用，实际中使用订单中的实付金额
        String url = payHelper.createPayUrl(orderId, "易购商城测试", /*order.getActualPay()*/1L);
        if (StringUtils.isBlank(url)) {
            throw new EgoException(ExceptionEnum.CREATE_PAY_URL_ERROR);
        }

        //判断是否有支付日志
        PayLog payLog = payLogMapper.selectById(orderId);
        if (payLog == null) {
            //创建支付日志
            payLogService.save(orderId);
        }

        return url;

    }

    @Override
    public void submitSeckillOrder(String orderId, Long skuId, Long price, Long userId) {
        //判断库存

        //4张订单表  order,orderDetail,orderStatus,seckillOrder
        //order
        Order order = new Order();
        order.setOrderId(Long.valueOf(orderId));
        order.setCreateTime(new Date());
        order.setUserId(userId);
        order.setCreateTime(new Date());
        order.setActualPay(price);
        order.setTotalPay(price);

        orderMapper.insert(order);

        OrderDetail orderDetail = new OrderDetail();
        Sku sku = goodsClient.querySkuById(skuId).getBody();
        orderDetail.setTitle(sku.getTitle());
        orderDetail.setOrderId(order.getOrderId());
        orderDetail.setSkuId(skuId);
        orderDetail.setPrice(order.getActualPay());
        orderDetail.setCount(1);
        orderDetail.setImage(sku.getImages());
        orderDetail.setOwnSpec(sku.getOwnSpec());

        orderDetailMapper.insert(orderDetail);

        //orderStatus
        OrderStatus orderStatus = OrderStatus.builder().orderId(order.getOrderId()).createTime(order.getCreateTime()).status(1).build();
        orderStatusMapper.insert(orderStatus);

        //TODO 新增秒杀订单
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setUserId(userId);
        seckillOrder.setOrderId(order.getOrderId());
        seckillOrder.setSkuId(skuId);
        seckillOrderMapper.insert(seckillOrder);
        //TODO 减库存
        //goodsClient.descrementSeckillStock(skuId);
    }

    @Override
    @Transactional(readOnly = true)
    public Boolean checkSeckillOrder(Long orderId) {
        Boolean result = false;
        Order order = orderMapper.selectById(orderId);
        if (order != null) {
            result = true;
        }
        return result;
    }

    @Override
    public ResultVO<Order> selectOrderPage(Integer page, Integer rows) {
        List<Order> list = new ArrayList<>();
        UserInfo user = LoginInterceptor.getCurrUser();
        Long userId = user.getId();
        Page<Order> orderPage = orderMapper.selectPage(new Page<>(page,rows), new QueryWrapper<Order>().eq("user_id", userId));
        List<Order> orders = orderPage.getRecords();
        for (Order order : orders) {
            Long orderId = order.getOrderId();
            List<OrderDetail> details = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId));
            for (OrderDetail detail : details) {
                detail.setStringOrderId(String.valueOf(detail.getOrderId()));
            }
            order.setOrderDetails(details);
            OrderStatus orderStatus = orderStatusMapper.selectById(orderId);
            order.setOrderStatus(orderStatus);
            list.add(order);
        }
        orderPage.setRecords(list);
        return new ResultVO<>(orderPage.getRecords(),orderPage.getTotal());
    }

    @Override
    public ResultVO<Order> selectStatusOrderPage(Integer status, Integer page, Integer rows) {
        ResultVO<Order> resultVO = selectOrderPage(page, rows);
        List<Order> items = resultVO.getItems();
        List<Order> orders = items.stream().map(item -> {
            if (item.getOrderStatus().getStatus().equals(status)) {
                return item;
            }
            return null;
        }).collect(Collectors.toList());
        resultVO.setItems(orders);
        resultVO.setTotal(Long.valueOf(String.valueOf(orders.size())));
        return resultVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cancelOrder(Long orderId) {
        Integer count = 0;
        try {
            count += orderStatusMapper.deleteById(orderId);
            count += orderDetailMapper.delete(new QueryWrapper<OrderDetail>().eq("order_id", orderId));
            count += orderMapper.delete(new QueryWrapper<Order>().eq("order_id",orderId));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
}
